home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
amiga
/
fractal
/
retinmnd.lha
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-18
|
8KB
|
330 lines
/* main.c
This is a quickie program to generate a mandelbrot set on a Retina
screen in 256 colors. */
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#ifdef _M68881
#include <m68881.h>
#endif
#include <exec/libraries.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <devices/timer.h>
#include <clib/alib_protos.h>
#include <time.h>
#include <pragmas/exec_pragmas.h>
#include <pragmas/intuition_pragmas.h>
#include "retina.h"
#include "retina_protos.h"
#include "retina_pragmas.h"
#define MAX_ORBITS 256
/* uncomment the following line to use my_RectFill */
#define MYRECTFILL 1
/* uncomment the following line to avoid repeating calculations */
/* WARNING: For some reason this creates code that will cause
stack overflow errors on any image larger than 320x400 or so */
/*
#define NOREPEATCALC
*/
struct BrotPoint {
unsigned int x, y;
double r, i;
#ifndef NOREPEATCALC
int orbits; /* -2 if untested, -1 if never escapes,
>= 0 otherwise */
#endif
};
static int max_orbits = MAX_ORBITS;
void Compute_Block(struct BrotPoint, struct BrotPoint);
short int __inline __regargs Test_Point(double, double);
#ifdef MYRECTFILL
void __inline __regargs my_RectFill(unsigned int, unsigned int,
unsigned int, unsigned int);
#endif
/* stack space must be BIG */
long __stack = 100000;
/* version string */
UBYTE vers[] = "$VER: RetinaMand V0.1 (18.7.93)";
extern struct IntuitionBase *IntuitionBase;
struct _xy_RetinaBase *RetinaBase;
struct DefaultScreenInfo screen_info;
int __oslibversion = 37;
double dr, di;
struct RetinaScreen *rScreen;
int main(int argc, char *argv[])
{
register int i, rstep, gstep, bstep;
register UBYTE foo, bar, baz;
struct BrotPoint start, end;
if ((RetinaBase = (struct _xy_RetinaBase *)
OpenLibrary("retina.library", 2L)) != NULL) {
if ((IntuitionBase = (struct IntuitionBase *)
OpenLibrary("intuition.library", 37L)) != NULL) {
if ((rScreen = Retina_OpenScreen(RSCR_STDWIDTH, RSCR_STDHEIGHT,
MID_DEFAULT_08,
RSFF_AUTOADJUST, 0L))
!= NULL) {
printf("Screen Opened successfully: %d by %d\n",
rScreen->_rs_Width, rScreen->_rs_Height);
/* set up screen colors; color 0 must always be black */
Retina_SetPalette(rScreen, 0, 0, 0, 0);
srand48((long) time(NULL));
foo = (lrand48() >> 3) % 256;
bar = (lrand48() >> 4) % 256;
baz = (lrand48() >> 3) % 256;
rstep = bstep = (lrand48() >> 5) % 16;
gstep = (lrand48() >> 5) % 10;
for (i = 1; i < 256; i++) {
Retina_SetPalette(rScreen, i, foo, bar, baz);
foo += rstep; foo %= 256;
bar += gstep; bar %= 256;
baz += bstep; baz %= 256;
}
Retina_SetDrMd(rScreen, RDM_JAM1);
dr = (2.0 - (-2.0))/((double) rScreen->_rs_Width);
di = (-1.5 - 1.5)/((double) rScreen->_rs_Height);
/* OK, folks, enough initializing. Let's call the
Mbrot routine. */
start.x = 0; start.r = -2.0; start.y = 0; start.i = 1.5;
end.x = rScreen->_rs_Width >> 1; end.r = 0.0;
end.y = rScreen->_rs_Height >> 1; end.i = 0.0;
#ifndef NOREPEATCALC
start.orbits = -2;
end.orbits = -2;
#endif
Compute_Block(start, end);
start.y = end.y + 1; start.i = end.i + di;
end.y = rScreen->_rs_Height - 1; end.i = -1.5;
Compute_Block(start, end);
start.x = end.x + 1; start.r = end.r + dr;
end.x = rScreen->_rs_Width - 1; end.r = 2.0;
Compute_Block(start, end);
start.y = 0; start.i = 1.5;
end.y = rScreen->_rs_Height >> 1; end.i = 0.0;
Compute_Block(start, end);
printf("Hit any key to quit.\n");
getch();
Retina_CloseScreen(rScreen);
}
else {
fprintf(stderr, "Unable to open Retina screen.\n");
}
}
else {
fprintf(stderr, "Can't open intuition.library V37+\n");
}
}
else {
fprintf(stderr, "Can not open retina.library!\n");
}
}
void Compute_Block(struct BrotPoint uleft, struct BrotPoint lright)
{
unsigned int i;
double j;
short int q, z;
if (lright.x - uleft.x < 2 && lright.y - uleft.y < 2) {
#ifdef NOREPEATCALC
q = Test_Point(uleft.r, uleft.i);
if (q > 0) Retina_SetPixel(rScreen, uleft.x, uleft.y, q);
#else
if (uleft.orbits == -2)
uleft.orbits = Test_Point(uleft.r, uleft.i);
if (uleft.orbits > 0) Retina_SetPixel(rScreen, uleft.x, uleft.y,
uleft.orbits);
#endif
q = Test_Point(uleft.r, lright.i);
if (q > 0) Retina_SetPixel(rScreen, uleft.x, lright.y, q);
#ifdef NOREPEATCALC
q = Test_Point(lright.r, lright.i);
if (q > 0) Retina_SetPixel(rScreen, lright.x, lright.y, q);
#else
if (lright.orbits == -2)
lright.orbits = Test_Point(lright.r, lright.i);
if (lright.orbits > 0) Retina_SetPixel(rScreen,
lright.x, lright.y,
lright.orbits);
#endif
q = Test_Point(lright.r, uleft.i);
if (q > 0) Retina_SetPixel(rScreen, lright.x, uleft.y, q);
return;
}
/* draw a box -- if the borders are all the same, then fill it that
color */
q = Test_Point(uleft.r, uleft.i); uleft.orbits = q;
if (q > 0)
Retina_SetPixel(rScreen, uleft.x, uleft.y, q);
z = Test_Point(lright.r, lright.i); lright.orbits = z;
if (z > 0)
Retina_SetPixel(rScreen, lright.x, lright.y, z);
if (z != q) {
goto recurse;
}
/* top & bottom */
for (i = uleft.x, j = uleft.r; i <= lright.x; i++, j += dr) {
z = Test_Point(j, uleft.i);
if (z != q) {
goto recurse;
}
else {
if (z > 0)
Retina_SetPixel(rScreen, i, uleft.y, z);
}
z = Test_Point(j, lright.i);
if (z != q) {
goto recurse;
}
else {
if (z > 0)
Retina_SetPixel(rScreen, i, lright.y, z);
}
}
/* left and right */
for (i = uleft.y, j = uleft.i; i <= lright.y; i++, j += di) {
z = Test_Point(uleft.r, j);
if (z != q) {
goto recurse;
}
else {
if (z > 0)
Retina_SetPixel(rScreen, uleft.x, i, z);
}
z = Test_Point(lright.r, j);
if (z != q) {
goto recurse;
}
else {
if (z > 0)
Retina_SetPixel(rScreen, lright.x, i, z);
}
}
/* if we passed through all that, we draw a filled rectangle */
if (q > 0) {
Retina_SetAPen(rScreen, q);
#ifdef MYRECTFILL
my_RectFill(uleft.x, uleft.y, lright.x, lright.y);
#else
/* fakin' it with line drawing */
for (i = uleft.y; i <= lright.y; i++)
Retina_Line(rScreen, uleft.x, i, lright.x, i);
#endif
}
return;
recurse:
{
struct BrotPoint top, bot, left, right, middle;
top.x = bot.x = middle.x = (uleft.x + lright.x) >> 1;
left.y = right.y = middle.y = (uleft.y + lright.y) >> 1;
top.r = bot.r = middle.r = (uleft.r + lright.r)/2.0;
left.i = right.i = middle.i = (uleft.i + lright.i)/2.0;
top.y = uleft.y; top.i = uleft.i;
bot.y = lright.y; bot.i = lright.i;
left.x = uleft.x; left.r = uleft.r;
right.x = lright.x; right.r = lright.r;
#ifndef NOREPEATCALC
middle.orbits = top.orbits = bot.orbits = left.orbits =
right.orbits = -2;
#endif
Compute_Block(uleft, middle);
#ifdef NOREPEATCALC
left.y += 1; left.i += di;
#endif
Compute_Block(left, bot);
#ifdef NOREPEATCALC
middle.x += 1; middle.y += 1;
middle.r += dr; middle.i += di;
top.x += 1; top.r += dr;
#endif
Compute_Block(middle, lright);
Compute_Block(top, right);
}
}
#ifdef MYRECTFILL
void __inline __regargs my_RectFill(unsigned int x1, unsigned int y1,
unsigned int x2, unsigned int y2)
{
short int tx1, tx2, v;
/* a little magic because Retina_RectFill() ignores the low-order
3 bits of the x-coords for 256-color screens */
tx1 = (x1 >> 3) + 1; tx2 = (x2 >> 3) - 1;
tx1 <<= 3; tx2 <<= 3;
if (tx2 > tx1) {
Retina_RectFill(rScreen, tx1, y1, tx2, y2);
if (x2 - tx2 > 1) {
for (v = tx2; v <= x2; v++)
Retina_Line(rScreen, v, y1, v, y2);
}
if (tx1 - x1 > 1) {
for (v = x1; v <= tx1; v++)
Retina_Line(rScreen, v, y1, v, y2);
}
}
else {
/* fake it with line drawing */
for (v = y1; v <= y2; v++) {
Retina_Line(rScreen, x1, v, x2, v);
}
}
}
#endif
/* Test_Point() tests points in the C plane to determine
whether they orbit stably or escape to infinity.
Returns the escape velocity or -1 if the point is
in the M-set. */
short int __inline __regargs Test_Point(double cx, double cy)
{
double x = 0.0, y = 0.0, tx;
register short int i;
/* z = z^2 + c */
for (i = 0; i < max_orbits; i++) {
tx = x*x - y*y + cx;
y = 2.0 * x * y + cy;
x = tx;
if (x*x + y*y > 4.0) {
return(i);
}
}
return(-1);
}